package com.vids.task;

import com.vids.mapper.ImageComparedDetailMapper;
import com.vids.mapper.ImageComparedSummaryMapper;
import com.vids.model.entity.ImageComparedDetail;
import com.vids.model.entity.ImageComparedSummary;

import lombok.extern.slf4j.Slf4j;

import java.io.File;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Map;

@Slf4j
public class ImageComparedTask implements Runnable {
    // map
    private Map<String, String> taskMap;

    private int indexThread;

    private int maxThreads;

    private String image_type_name;

    private int image_type;
    private ImageComparedSummaryMapper imageComparedSummaryMapper;

    private ImageComparedDetailMapper imageComparedDetailMapper;

    public ImageComparedSummaryMapper getImageComparedSummaryMapper() {
        return imageComparedSummaryMapper;
    }

    public void setImageComparedSummaryMapper(ImageComparedSummaryMapper imageComparedSummaryMapper) {
        this.imageComparedSummaryMapper = imageComparedSummaryMapper;
    }

    public ImageComparedDetailMapper getImageComparedDetailMapper() {
        return imageComparedDetailMapper;
    }

    public void setImageComparedDetailMapper(ImageComparedDetailMapper imageComparedDetailMapper) {
        this.imageComparedDetailMapper = imageComparedDetailMapper;
    }

    private final Object detailLock = new Object();

    private final Object summaryLock = new Object();

    private final Object compareImageLock = new Object();

    public Map<String, String> getMap() {
        return taskMap;
    }

    public void setMap(Map<String, String> taskMap) {
        this.taskMap = taskMap;
    }

    private String viid_root = "/mount/data1/viid_picture/";
    private String ape_root = "/mount/data1/picture/";

    public ImageComparedTask(Map<String, String> taskMap, int indexThread, int maxThreads, String image_type_name) {
        this.taskMap = taskMap;
        this.indexThread = indexThread;
        this.maxThreads = maxThreads;
        this.image_type_name = image_type_name;

        //  目标类型 TargetType 1：人员，2：人脸，3：机动车，4：非机动车，5：物品，6：场景
        if (this.image_type_name.equals("person")) {
            this.image_type = 1;
        } else if (this.image_type_name.equals("face")) {
            this.image_type = 2;
        } else if (this.image_type_name.equals("motor")) {
            this.image_type = 3;
        } else if (this.image_type_name.equals("non_motor")) {
            this.image_type = 4;
        } else {
            this.image_type = 99;
        }
        log.info("taskMap size= {}, image_type is {}, image_type_name={}", this.taskMap.size(), this.image_type, image_type_name);
    }


    public void compareImage(String viid_apeid_dir, String ape_apeid_dir, String ape_id,
                             String ape_ip_addr, int image_type,
                             int compared_hour, LocalDateTime toHandleDateTime) {
        File f_viid_apeid_dir = new File(viid_apeid_dir);
        File[] viid_files = f_viid_apeid_dir.listFiles();

        File f_ape_apeid_dir = new File(ape_apeid_dir);
        File[] ape_files = f_ape_apeid_dir.listFiles();

        int ape_amount = 0;
        int viid_amount = 0;
        if (ape_files != null) {
            ape_amount = ape_files.length;
        } else {
            log.error("compareImage：ape_files is null.");
        }

        if (viid_files != null) {
            viid_amount = viid_files.length;
        } else {
            log.error("compareImage：viid_files is null.");
        }

        log.info("====> image_type={},ape_id={}:ape_ip_addr={}, viid_files count={}", image_type, ape_id, ape_ip_addr, viid_amount);
        log.info("====> image_type={},ape_id={}:ape_ip_addr={}, ape_files count= {}", image_type, ape_id, ape_ip_addr, ape_amount);

        try {
            ImageComparedDetail detail = null;
            ImageComparedSummary summary = new ImageComparedSummary();
            int result = -1;
            Integer matchedCount = 1234;

//            if (viid_amount >= ape_amount) {
//                for (File vf : viid_files) {
//                    detail = new ImageComparedDetail();
//
//                    detail.setViidImage(vf.getName());
//
//                    String dateStr = vf.getName().substring(22, 36);
//                    detail.setViidImageCreateTime(LocalDateTime.parse(dateStr, DateTimeFormatter.ofPattern("yyyyMMddHHmmss")));
//
//                    detail.setApeId(ape_id);
//                    detail.setApeIpAddr(ape_ip_addr);
//
//                    result = -1;
//
//                    //已经匹配完的，需要从集合中去掉，防止下次继续匹配，可以做个标记。  for (File af : ape_files) {
//                    for (int i = 0; i < ape_files.length; i++) {
//                        File af = ape_files[i];
//                        if (null == af)
//                            continue;
//
//                        result = dateStr.compareTo(af.getName().substring(22, 36));
//                        if (result == 0) {
//
//                            detail.setApeImage(af.getName());
//                            detail.setApeImageCreateTime(LocalDateTime.parse(af.getName().substring(22, 36),
//                                    DateTimeFormatter.ofPattern("yyyyMMddHHmmss")));
//                            detail.setComparedResult(0);
//
//                            //已经匹配完的，需要将其数组元素置为null，防止下次继续匹配
//                            synchronized (detailLock) {
//                                ape_files[i] = null;
//                            }
//                            break;
//                        }
//                    }
//
//                    if (result != 0) {
//                        detail.setComparedResult(1);
//                        detail.setApeImage("");
//                    } else {
//                        matchedCount++;
//                    }
//
//                    detail.setImageType(image_type);
//                    detail.setComparedHour(compared_hour);
//                    //将比较结果添加到数据库的详情表中。
//                    synchronized (detailLock) {  // 同步代码块
//                        imageComparedDetailMapper.insert(detail);
//                    }
//                }
//            } else {
//                for (File af : ape_files) {
//                    detail = new ImageComparedDetail();
//
//                    detail.setApeImage(af.getName());
//                    detail.setApeImageCreateTime(LocalDateTime.parse(af.getName().substring(22, 36),
//                            DateTimeFormatter.ofPattern("yyyyMMddHHmmss")));
//
//                    detail.setApeId(ape_id);
//                    detail.setApeIpAddr(ape_ip_addr);
//
//                    result = -1;
//
//                    for (int i = 0; i < viid_files.length; i++) {
//                        File vf = viid_files[i];
//                        if (null == vf)
//                            continue;
//
//                        result = af.getName().substring(22, 36).compareTo(vf.getName().substring(22, 36));
//                        if (result == 0) {
//
//                            detail.setViidImage(vf.getName());
//                            detail.setViidImageCreateTime(LocalDateTime.parse(vf.getName().substring(22, 36),
//                                    DateTimeFormatter.ofPattern("yyyyMMddHHmmss")));
//                            detail.setComparedResult(0);
//
//                            //已经匹配完的，需要将其数组元素置为null，防止下次继续匹配
//                            synchronized (detailLock) {
//                                viid_files[i] = null;
//                            }
//                            break;
//                        }
//                    }
//
//                    if (result != 0) {
//                        detail.setComparedResult(1);
//                        detail.setViidImage("");
//                    } else {
//                        matchedCount++;
//                    }
//
//                    //将比较结果添加到数据库的详情表中。
//                    detail.setImageType(image_type);
//                    detail.setComparedHour(compared_hour);
//                    synchronized (detailLock) {  // 同步代码块
//                        imageComparedDetailMapper.insert(detail);
//                    }
//
//                }
//            }

            summary.setApeId(ape_id);
            summary.setApeIpAddr(ape_ip_addr);
            summary.setImageType(image_type);
            summary.setViidImageAmount(viid_amount);
            summary.setApeImageAmount(ape_amount);
            summary.setMatchedAmount(matchedCount);
            summary.setComparedHour(compared_hour);

            String datePath = toHandleDateTime.format(DateTimeFormatter.ofPattern("yyyyMMdd"));
            int comparedHour = toHandleDateTime.getHour();

            String beginTime;
            String endTime;

            if (comparedHour < 10) {
                beginTime = datePath + "0" + comparedHour + "0000";
            } else {
                beginTime = datePath + comparedHour + "0000";
            }

            if (comparedHour != 23) {
                if (comparedHour < 9) {
                    endTime = datePath + "0" + (comparedHour + 1) + "0000";
                } else {
                    endTime = datePath + (comparedHour + 1) + "0000";
                }
            } else {
                endTime = datePath + comparedHour + "5959";
            }
            summary.setImageBeginCreateTime(LocalDateTime.parse(beginTime, DateTimeFormatter.ofPattern("yyyyMMddHHmmss")));
            summary.setImageEndCreateTime(LocalDateTime.parse(endTime, DateTimeFormatter.ofPattern("yyyyMMddHHmmss")));
            log.info("ZMCAAAA" + summary.toString());
            synchronized (summaryLock) {  // 同步代码块
                log.info("ZMCBBBBB" + summary.toString());
                int insert = imageComparedSummaryMapper.insert(summary);
                log.info("ZMCCCCCC" + insert);

            }
        } catch (Exception e) {
            log.error("compareImage insert failed", e);
        }
    }

    private ArrayList<String> getCommonFiles(File[] viid_files, File[] ape_files) {
        ArrayList<String> commonFiles = new ArrayList<>();
        if (viid_files == null || ape_files == null) {
            log.error("有空值，不予比较");
            return commonFiles;
        }
        for (File viidFile : viid_files) {
            for (File apeFile : ape_files) {

                if (viidFile.getName().equals(apeFile.getName())) {
                    if (viidFile.isDirectory()) {
                        commonFiles.add(viidFile.getName());
                        break;
                    }
                }
            }
        }

        return commonFiles;
    }

    private ArrayList<String> getDiffFiles(File[] one_files, ArrayList<String> commonFiles) {

        ArrayList<String> diffFiles = new ArrayList<>();
        for (File file : one_files) {
            if (!commonFiles.contains(file.getName())) {
                if (file.isDirectory()) {
                    diffFiles.add(file.getName());
                }
            }
        }

        return diffFiles;
    }

    public void insertDBImage(boolean imageFromViid, String apeid_dir, String ape_id,
                              String ape_ip_addr, int image_type,
                              int compared_hour, LocalDateTime toHandleDateTime) {
        try {
            File f_apeid_dir = new File(apeid_dir);
            File[] apeid_files = f_apeid_dir.listFiles();

            if (apeid_files == null) {
                log.error("apeid_files is null");
                return;
            }

            int files_amount = apeid_files.length;
            if (files_amount == 0) {
                log.info("files_amount = 0" + apeid_dir + imageFromViid);
                return;
            }

            // 在详情表中增加记录
//            ImageComparedDetail detail = null;
//            for (File vf : apeid_files) {
//                detail = new ImageComparedDetail();
//
//                detail.setViidImage(vf.getName());
//                detail.setApeId(ape_id);
//                detail.setApeIpAddr(ape_ip_addr);
//                String dateStr = vf.getName().substring(22, 36);
//
//                if (imageFromViid) {
//                    detail.setViidImage(vf.getName());
//                    detail.setViidImageCreateTime(LocalDateTime.parse(dateStr,
//                            DateTimeFormatter.ofPattern("yyyyMMddHHmmss")));
//                } else {
//                    detail.setApeImage(vf.getName());
//                    detail.setApeImageCreateTime(LocalDateTime.parse(dateStr,
//                            DateTimeFormatter.ofPattern("yyyyMMddHHmmss")));
//                }
//                detail.setComparedResult(1);
//                detail.setImageType(image_type);
//                detail.setComparedHour(compared_hour);
//                synchronized (detailLock) {  // 同步代码块
//                    imageComparedDetailMapper.insert(detail);
//                }
//            }

            ImageComparedSummary summary = new ImageComparedSummary();

            summary.setApeId(ape_id);
            summary.setApeIpAddr(ape_ip_addr);
            summary.setImageType(image_type);
            if (imageFromViid) {
                summary.setViidImageAmount(files_amount);
                summary.setApeImageAmount(0);
            } else {
                summary.setViidImageAmount(0);
                summary.setApeImageAmount(files_amount);
            }

            summary.setMatchedAmount(0);
            summary.setComparedHour(compared_hour);

            String datePath = toHandleDateTime.format(DateTimeFormatter.ofPattern("yyyyMMdd"));
            int comparedHour = toHandleDateTime.getHour();

            String beginTime;
            String endTime;

            if (comparedHour < 10) {
                beginTime = datePath + "0" + comparedHour + "0000";
            } else {
                beginTime = datePath + comparedHour + "0000";
            }

            if (comparedHour != 23) {
                if (comparedHour < 9) {
                    endTime = datePath + "0" + (comparedHour + 1) + "0000";
                } else {
                    endTime = datePath + (comparedHour + 1) + "0000";
                }
            } else {
                endTime = datePath + comparedHour + "5959";
            }
            summary.setImageBeginCreateTime(LocalDateTime.parse(beginTime, DateTimeFormatter.ofPattern("yyyyMMddHHmmss")));
            summary.setImageEndCreateTime(LocalDateTime.parse(endTime, DateTimeFormatter.ofPattern("yyyyMMddHHmmss")));

            synchronized (summaryLock) {  // 同步代码块
                log.info("ZMCDDDD"+summary.toString());
                int insert = imageComparedSummaryMapper.insert(summary);
                log.info("ZMCEEEE"+insert);
            }
        } catch (Exception e) {
            log.error("insertDBImage insert failed", e);
        }
    }

    /**
     * 图片比对算法：
     * 1、先取得 两类采集来源对应图片类型目录（face\motor）下设备（Ape）列表交集，即两个目录中都存在的设备列表集合。
     * 2、比较两个目录下的图片，是否为相同图片。
     * 3、不在交集中的Ape，只统计其个数，在汇总表中记录，详情表中记录图片名称（是否必要？）。
     */
    @Override
    public void run() {
        LocalDateTime toHandleDateTime = LocalDateTime.now().minusHours(1);
        String datePath = toHandleDateTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
        int comparedHour = toHandleDateTime.getHour();

        String viid_dir = viid_root + datePath + "/" + comparedHour + "/" + image_type_name + "/";
        String ape_dir = ape_root + datePath + "/" + comparedHour + "/" + image_type_name + "/";

        //查询两个目录下的所有apeID，并组成一个总的任务列表，并按照indexThread分段，分成n个子任务，让n个线程进行并发处理。
        File total_viid_dir = new File(viid_dir);
        File[] viid_files = total_viid_dir.listFiles();
        int viid_total = 0;
        if (viid_files != null) {
            viid_total = viid_files.length;
        }

        File total_ape_dir = new File(ape_dir);
        File[] ape_files = total_ape_dir.listFiles();

        int ape_total = 0;
        if (ape_files != null) {
            ape_total = ape_files.length;
        }
        log.info("viid_total" + viid_total);
        log.info("ape_total" + ape_total);

        ArrayList<String> commonFiles = getCommonFiles(viid_files, ape_files);
        ArrayList<String> OnlyViidExistFiles = new ArrayList<>();
        ArrayList<String> OnlyApeExistFiles = new ArrayList<>();
        if (commonFiles == null || commonFiles.size() == 0) {
            if (ape_files != null) {
                ArrayList<String> diffFiles = new ArrayList<>();
                for (File file : ape_files) {
                    if (file.isDirectory()) {
                        diffFiles.add(file.getName());
                    }
                }
                OnlyApeExistFiles = diffFiles;
            }
            if (viid_files != null) {
                ArrayList<String> diffFiles = new ArrayList<>();
                for (File file : viid_files) {
                    if (file.isDirectory()) {
                        diffFiles.add(file.getName());
                    }
                }
                OnlyViidExistFiles = diffFiles;
            }
        } else {
            OnlyViidExistFiles = getDiffFiles(viid_files, commonFiles);
            OnlyApeExistFiles = getDiffFiles(ape_files, commonFiles);
        }
        int total_task_num = 0;
        if (commonFiles != null) {
            total_task_num = commonFiles.size();
        }


        String s_viid_apeid_dir;
        String s_ape_apeid_dir;
        String ape_ip_addr;
        log.info("ZMC1" + indexThread + "," + maxThreads);
        if (maxThreads == 1) {
            for (String apeId : commonFiles) {
                s_viid_apeid_dir = viid_dir + apeId;
                s_ape_apeid_dir = ape_dir + apeId;
                ape_ip_addr = taskMap.get(apeId);
                if (ape_ip_addr == null) {
                    ape_ip_addr = "";
                }

                compareImage(s_viid_apeid_dir, s_ape_apeid_dir, apeId,
                        ape_ip_addr, this.image_type,
                        comparedHour, toHandleDateTime);
            }
            log.info("ZMC1" + indexThread + "," + maxThreads);

            for (String apeId : OnlyViidExistFiles) {
                s_viid_apeid_dir = viid_dir + apeId;
                ape_ip_addr = taskMap.get(apeId);
                if (ape_ip_addr == null) {
                    ape_ip_addr = "";
                }
                log.info("ZMC1" + indexThread + "," + maxThreads);
                insertDBImage(true, s_viid_apeid_dir, apeId,
                        ape_ip_addr, this.image_type,
                        comparedHour, toHandleDateTime);
            }

            for (String apeId : OnlyApeExistFiles) {
                s_ape_apeid_dir = ape_dir + apeId;
                ape_ip_addr = taskMap.get(apeId);
                if (ape_ip_addr == null) {
                    ape_ip_addr = "";
                }

                insertDBImage(false, s_ape_apeid_dir, apeId,
                        ape_ip_addr, this.image_type,
                        comparedHour, toHandleDateTime);
            }

        }

        if (maxThreads > 2) {
            log.info("ZMC1" + indexThread + "," + maxThreads);
            if (indexThread < (maxThreads - 2)) {

                if (total_task_num == 0) {
                    log.error("total_task_num is 0");
                }
                int workThreads = maxThreads - 2;
                int taskIndBegin = (total_task_num / workThreads) * (indexThread);
                int taskIndEnd = (total_task_num / workThreads) * (indexThread + 1);

                for (int i = taskIndBegin; i < taskIndEnd; i++) {
                    String apeId = commonFiles.get(i);

                    s_viid_apeid_dir = viid_dir + apeId;
                    s_ape_apeid_dir = ape_dir + apeId;
                    ape_ip_addr = taskMap.get(apeId);
                    if (ape_ip_addr == null) {
                        continue;
                    }

                    compareImage(s_viid_apeid_dir, s_ape_apeid_dir, apeId,
                            ape_ip_addr, this.image_type,
                            comparedHour, toHandleDateTime);
                }
            } else if (indexThread == (maxThreads - 2)) {
                for (String apeId : OnlyViidExistFiles) {
                    s_viid_apeid_dir = viid_dir + apeId;
                    ape_ip_addr = taskMap.get(apeId);
                    if (ape_ip_addr == null) {
                        continue;
                    }
                    insertDBImage(true, s_viid_apeid_dir, apeId,
                            ape_ip_addr, this.image_type,
                            comparedHour, toHandleDateTime);
                }

            } else if (indexThread == (maxThreads - 1)) {
                for (String apeId : OnlyApeExistFiles) {
                    s_ape_apeid_dir = ape_dir + apeId;
                    ape_ip_addr = taskMap.get(apeId);
                    if (ape_ip_addr == null) {
                        continue;
                    }

                    insertDBImage(false, s_ape_apeid_dir, apeId,
                            ape_ip_addr, this.image_type,
                            comparedHour, toHandleDateTime);
                }

            } else {
                log.error("indexThread or maxThreads error: indexThread = " + indexThread + ", maxThreads = " + maxThreads);
            }

        } else {
            log.info("ZMC1" + indexThread + "," + maxThreads);
            log.error("maxThreads 不能等于2");
        }


    }
}
